[小ネタ] LocalStackとAWS SDK v3を用いたテストの際に、S3との接続がうまく行かない場合の対処法
事業本部 Delivery 部のアベシです。
LocalStackとAWS SDK v3を使ったLambda関数のローカルテストで、LocalStack上のS3にうまく接続できないエラーが発生しました。
最初、エラーの内容から何が問題なのかわからず困ったので小ネタではありますがどう対処したか紹介したいと思います。
実行環境
各モジュールのバージョンは以下となります。
項目名 | バージョン |
---|---|
AWS SDK | v2からv3に変更 |
LocalStack | 2.14.0 |
背景
テスト対象のLambdaのNode.jsを18に変更するに当たって、元々AWS SDK v2
で書かれていたテストコードをv3
にバージョンアップし、テストを実行したところ今回の問題が発生しました。
今回v3に変更したテストコードが2つあり、便宜上①、②とします。
コードによってエラーの内容が異なっていましたが、どちらも内容からは原因がわかりませんでした。
実際のエラー
実際に発生したエラーはコードによって違いましたが、どちらのLambda関数も基本的にやっていることは同じで、S3に保存したオブジェクトを取得して返す
というシンプルなものです。
1. 発生したエラー 1
InvalidBucketName: The specified bucket is not valid.
- 発生したエラー 2
500: UnknownError
原因調査
LocalStackのリポジトリでissueを検索してみると、似たような症状についてやり取りしているissueがいくつか見つかりました。
そのうちの一つが以下です。
この記事に対処方法が2つ提案されており、今回のエラーの原因がS3へのエンドポイントの指定方法によるものと予想しました。
※ S3のエンドポイントの指定方法にはパス形式
と仮想ホスト形式
の2通りがあります。
対処方法
① S3のエンドポイント指定を仮想ホスト形式
用の表記にする
SDKのデフォルトは仮想ホスト形式
となっており、S3へのエンドポイントをhttps://localhost:4566
と指定する場合パス形式
の指定方法となるとのことです。
このため指定したエンドポイントに接続できずにエラーが発生したようです。
仮想ホスト形式
に対応したパスはS3個別のエンドポイントとなるhttps://s3.localhost.localstack.cloud:4566
です。
LocalStackのS3のGettingStartのページにも現在は仮想ホスト形式
の使用を推奨すると記載がありました。
② forcePathStyle: true
でパス形式を強制する
S3Clientクラスを newする時のパラメーターにforcePathStyle: true
を追加することでパス形式
を強制することでもエラーの解消は可能でした。
テストコードの修正
元々のコードが以下のようにになります
const s3Client = new S3Client({ endpoint: `https://localhost:4566`, region: 'ap-northeast-1', });
修正を施したコードは以下のようになります。
対処方法①を適応
const s3Client = new S3Client({ endpoint: `https://s3.localhost.localstack.cloud:4566`, region: 'ap-northeast-1', });
対処方法②を適応
const s3Client = new S3Client({ endpoint: `https://localhost:4566`, region: 'ap-northeast-1', forcePathStyle: true });
これらの修正を施すとテストがパスするようになりました。
以上。